package handlers

import (
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
	"log"
	"net/http"
	"week32/api/request"
	"week32/dao"
	"week32/pkg"
)

func Login(c *gin.Context) {
	var data request.LoginRequest
	err := c.ShouldBind(&data)
	if err != nil {
		c.JSON(http.StatusOK, gin.H{
			"Code": 500,
			"Msg":  "失败",
			"Data": nil,
		})
		return
	}

	result := dao.Login(data.Tel, data.Password)
	if result.Id == 0 {
		dao.Register(data.Tel, data.Password)
	}

	var claims = pkg.CustomClaims{
		ID: uint(result.Id),
	}
	token, err := pkg.NewJWT("zj").CreateToken(claims)
	if err != nil {
		c.JSON(http.StatusOK, gin.H{
			"Code": 500,
			"Msg":  "token生成失败",
			"Data": nil,
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"Code": 200,
		"Msg":  "Success",
		"Data": token,
	})
}

type WSRequest struct {
	Cmd  string      `json:"cmd"`
	Data interface{} `json:"data"`
}

type WSResponse struct {
	Code int         `json:"code"`
	Msg  string      `json:"msg"`
	Data interface{} `json:"data"`
}

func Chat(c *gin.Context) {
	userId := c.GetUint("userId")

	var upgrader = websocket.Upgrader{}

	conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
	if err != nil {
		log.Print("upgrade:", err)
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "websocket fail",
			"data": nil,
		})
		return
	}

	defer conn.Close()

	for {
		_, message, err := conn.ReadMessage()
		if err != nil {
			log.Println("read:", err)
			break
		}

		var req WSRequest

		err = json.Unmarshal(message, &req)
		if err != nil {
			WSRespErr(conn, 1000, "解析失败")
			continue
		}

		switch req.Cmd {
		case "online":
			go Online(conn, message, int(userId))
		case "send":
			go Send(conn, message, int(userId))
		default:
			WSRespErr(conn, 10001, "没有该方法")
		}
		WSRespSuccess(conn, "成功")
	}
}

type SendS struct {
	ToUserId int    `json:"to_user_id"`
	Message  string `json:"message"`
}

type WSSendReq struct {
	Cmd  string `json:"cmd"`
	Data SendS  `json:"data"`
}

func Send(conn *websocket.Conn, message []byte, userId int) {
	var req WSSendReq
	err := json.Unmarshal(message, &req)
	if err != nil {
		WSRespErr(conn, 20001, "解析失败")
		return
	}

	if OnlineUser[req.Data.ToUserId] == nil {
		WSRespErr(conn, 20003, "该用户不是好友")
		return
	}

	WSRespSuccess(OnlineUser[req.Data.ToUserId], req.Data.Message)

	WSRespSuccess(conn, "发送成功")

	dao.CreateSend(userId, req.Data.ToUserId, req.Data.Message)
}

var OnlineUser = make(map[int]*websocket.Conn)

func Online(conn *websocket.Conn, message []byte, userId int) {
	OnlineUser[userId] = conn
	fmt.Println(OnlineUser)
	WSRespSuccess(conn, userId)
}

func WSRespErr(conn *websocket.Conn, code int, msg string) {
	response := WSResponse{
		Code: code,
		Msg:  msg,
		Data: nil,
	}

	responseStr, err := json.Marshal(response)

	err = conn.WriteMessage(websocket.TextMessage, responseStr)
	if err != nil {
		log.Println("write:", err)
	}
}

func WSRespSuccess(conn *websocket.Conn, data interface{}) {
	response := WSResponse{
		Code: 0,
		Msg:  "ok",
		Data: data,
	}

	responseStr, err := json.Marshal(response)

	err = conn.WriteMessage(websocket.TextMessage, responseStr)
	if err != nil {
		log.Println("write:", err)
	}
}

func List(c *gin.Context) {
	user := dao.List()
	c.JSON(http.StatusOK, gin.H{
		"Code": 200,
		"Msg":  "Success",
		"Data": user,
	})
}

func ChatList(c *gin.Context) {
	chat := dao.ChatList()
	c.JSON(http.StatusOK, gin.H{
		"Code": 200,
		"Msg":  "Success",
		"Data": chat,
	})
}
